import json

from django.http import HttpResponseNotFound
from django.shortcuts import render
from django.views import View
# Create your views here.
from pro_mysite import settings
from utils.json_fun import to_json_data
from utils.res_code import Code, error_map
from . import models
from django.core.paginator import Paginator,EmptyPage, PageNotAnInteger
from . import constants
from haystack.views import SearchView as _SearchView
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page


import logging
logger = logging.getLogger('django')
# def index(request):
#     return render(request,'news/index.html')

# 新闻标签

@method_decorator(cache_page(timeout=200), name='dispatch')
class IndexView(View):

    def get(self,request):
        tags = models.Tag.objects.only('id','name').filter(is_delete=False)

        hot_news = models.HotNews.objects.select_related('news').\
            only('news__title','news__image_url','news__id').filter(is_delete=False).\
            order_by('priority','-news__clicks')[0:constants.HOT_NEWS_COUNT]

        return render(request,'news/index.html',locals())

# 新闻列表页面
# @method_decorator(cache_page(timeout=400,cache='page_cache'), name='dispatch')
class NewsListView(View):
    """
    1, 获取参数
    2，校验参数
    3， 数据库拿数据
    4，分页
    5，返回给前端
    :param   必传
    tag_id
    page
    """
    def get(self,request):

        try:
            tag_id = int(request.GET.get('tag_id',0))
        except Exception as e:
            logger.error("标签错误：\n{}".format(e))
            tag_id= 0

        # page
        try:
            page = int(request.GET.get('page',1))
        except Exception as e:
            logger.error("当前页数错误：\n{}".format(e))
            page = 1

        # 数据库取数据
        # select_related 一次性查出news关联的对象
        news_queryset = models.News.objects.select_related('tag','author').\
            only('title','digest','image_url','update_time','tag__name','author__username')

        news = news_queryset.filter(is_delete=False,tag_id=tag_id) or news_queryset.filter(is_delete=False)

        # 创建分页对象  待分页对象   每页显示数量
        paginator = Paginator(news,5)

        try:
            # page() 接受一个页码做为参数，返回当前页对象
            news_info = paginator.page(page)

        except EmptyPage:
            logging.info("用户访问的页数大于总页数")
            # num_pages  返回总页数
            news_info = paginator.page(paginator.num_pages)

        #
        news_info_list = []
        for n in news_info:
            news_info_list.append({
                'id':n.id,
                'title':n.title,
                'digest':n.digest,
                'image_url': n.image_url,
                'tag_name': n.tag.name,
                'author': n.author.username,
                'update_time':n.update_time.strftime('%Y年%m月%d日 %H:%M')

            })
        # 创建给前端返回的数据
        data = {
            'total_pages':paginator.num_pages,
            'news': news_info_list
        }
        return to_json_data(data=data)


# 轮播图功能接口
class NewsBanner(View):
    """
    /news/banners/
    前台不需要传参
    :param
    image_url
    news__id
    news__title
    """
    def get(self,request):
        banners = models.Banner.objects.select_related('news').\
            only('image_url','news__id','news__title').\
            filter(is_delete=False)[0:constants.SHOW_BANNER_COUNT]

        # 序列化输出
        banners_info_list = []
        for a in banners:
            banners_info_list.append({
                "image_url":a.image_url,
                "news_id":a.news.id,
                "news_title":a.news.title,
            })
        data = {
            'banners': banners_info_list
        }

        return to_json_data(data=data)

# 新闻详情
class NewsDetailView(View):
    def get(self,request,news_id):
        news = models.News.objects.select_related('tag','author').\
            only('title','content','update_time','author__username','tag__name').\
            filter(is_delete=False,id=news_id).first()
        if news:

            comments = models.Comments.objects.select_related('author','parent').\
                only('content','author__username','update_time',
                     'parent__content','parent__author__username','parent__update_time').\
                filter(is_delete=False,news_id=news_id)

            comments_list = []
            for comm in comments:
                comments_list.append(comm.to_dict_data())


            return render(request,'news/news_detail.html',locals())
        else:
            return HttpResponseNotFound('<h1>Page Not Found</h1>')


class NewsCommentView(View):
    """
    /news/<int:news_id>/comments/
    1, 判断用户是否已登录
    2，获取参数
    3，校验参数
    4，保存到数据库
    """
    def post(self,request,news_id):
        if not request.user.is_authenticated:

           return to_json_data(errno=Code.SESSIONERR, errmsg=error_map[Code.SESSIONERR])

        if not models.News.objects.only('id').filter(is_delete=False,id=news_id).exists():
            return to_json_data(errno=Code.PARAMERR, errmsg='新闻不存在！')

        # 2 获取参数
        json_data = request.body   # 一个汉字几个字节
        if not json_data:
            return to_json_data(errno=Code.PARAMERR,errmsg=error_map[Code.PARAMERR])

        dict_data = json.loads(json_data.decode('utf8'))

        #  一级评论内容
        content = dict_data.get('content')
        if not dict_data.get('content'):
            return to_json_data(errno=Code.PARAMERR, errmsg='评论内容不能为空！')

        # 回复评论 ---  二级评论
        parent_id = dict_data.get('parent_id')
        try:
            if parent_id:
                if not models.Comments.objects.only('id'). \
                    filter(is_delete=False, id=parent_id, news_id=news_id).exists():
                    return to_json_data(errno=Code.PARAMERR,errmsg=error_map[Code.PARAMERR])

        except Exception as e:
            logging.info('前台传的parent_id 异常：\n{}'.format(e))
            return to_json_data(errno=Code.PARAMERR, errmsg='未知异常')

        # 保存数据库
        news_content = models.Comments()
        news_content.content = content
        news_content.news_id = news_id
        news_content.author = request.user
        news_content.parent_id = parent_id if parent_id else None
        news_content.save()
        return to_json_data(data=news_content.to_dict_data())


class SearchView(_SearchView):

    # 模板文件
    template = 'news/search.html'

    def create_response(self):
        kw = self.request.GET.get('q', '')
        if not kw:
            show_all = True
            hot_news = models.HotNews.objects.select_related('news').\
                only('news__title','news__image_url','news__id').\
                filter(is_delete=False).order_by('priority','-news__clicks')
            # 参数
            paginator = Paginator(hot_news, 5)
            try: # 获取到传入的页码
                page = paginator.page(int(self.request.GET.get('page',1)))
                # 假如传的不是整数
            except PageNotAnInteger:
                # 返回第一页数据
                page = paginator.page(1)
            except EmptyPage:
                page = paginator.page(paginator.num_pages)
            return render(self.request, self.template, locals())

        else:
            show_all = False
            qs = super(SearchView, self).create_response()
            return qs



class SideView(View):

    def get(self,request,news_id):
        sides = models.News.objects.select_related('author','tag').\
            only('title','image_url','tag__name','update_time').filter(is_delete=False,id=news_id).first()

        return render(request,'news/side.html',locals())


